package com.gmadmin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gmadmin.entity.SysMenu;
import com.gmadmin.mapper.SysMenuMapper;
import com.gmadmin.payload.MenuQueryCriteria;
import com.gmadmin.service.SysMenuService;
import com.gmadmin.entity.vo.menu.MenuMetaVo;
import com.gmadmin.entity.vo.menu.NavMenuVo;
import com.gmadmin.entity.vo.menu.SysMenuVo;
import com.gmadmin.entity.vo.role.SysRoleVo;
import com.gmadmin.utils.CollectionBeanUtils;
import com.gmadmin.vo.PageVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import com.gmadmin.service.SysRoleService;

/**
 * @author zhangliang
 * @version 1.0
 * @date 2021/2/2 16:03
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {


    private final SysMenuMapper sysMenuMapper;

    private final SysRoleService sysRoleService;


    @Lazy
    public SysMenuServiceImpl(SysMenuMapper sysMenuMapper, SysRoleService sysRoleService) {
        this.sysMenuMapper = sysMenuMapper;
        this.sysRoleService = sysRoleService;
    }

    @Override
    public List<SysMenuVo> findByRoleIdList(Set<Long> ids) {
        List<SysMenu> menus = sysMenuMapper.findListByRoleIds(ids);
        return BeanUtil.copyToList(menus, SysMenuVo.class);
    }

    @Override
    public PageVo<SysMenuVo> findListByPage(MenuQueryCriteria criteria, Page<SysMenu> page) {
        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.isNull("pid");
        IPage<SysMenu> iPage = sysMenuMapper.selectPage(page, queryWrapper);
        List<SysMenu> menus = iPage.getRecords();
        List<SysMenuVo> menuVos = CollectionBeanUtils.copyListProperties(menus, SysMenuVo::new);

        PageVo<SysMenuVo> pageVo = new PageVo<>();
        pageVo.setItems(menuVos);
        pageVo.setTotal(iPage.getTotal());
        return pageVo;
    }

    @Override
    public List<SysMenuVo> findListByUserId(Long currentUserId) {
        List<SysRoleVo> roleVos = sysRoleService.selectByUserId(currentUserId);
        Set<Long> roleIds = roleVos.stream().map(SysRoleVo::getId).collect(Collectors.toSet());
        return findByRoleIdList(roleIds);
    }

    @Override
    public List<SysMenuVo> buildTree(List<SysMenuVo> menuVos) {
        // 根节点菜单
        List<SysMenuVo> rootMenu = menuVos.stream().
                filter(m -> Objects.isNull(m.getPid())).collect(Collectors.toList());
        List<SysMenuVo> childMenuVos = menuVos.stream().filter(m -> Objects.nonNull(m.getPid())).collect(Collectors.toList());

        return rootMenu.stream().peek(sysMenuVo -> sysMenuVo.setChildren(collectTreeData(sysMenuVo, childMenuVos))
        ).collect(Collectors.toList());
    }

    @Override
    public List<SysMenuVo> collectTreeData(SysMenuVo sysMenuVo, List<SysMenuVo> menuVoList) {

        return menuVoList.stream().filter(m -> m.getPid().equals(sysMenuVo.getId()))
                .peek(m -> m.setChildren(collectTreeData(m, menuVoList))
                ).collect(Collectors.toList());
    }

    @Override
    public List<NavMenuVo> buildMenus(List<SysMenuVo> menuVosTree) {
        List<NavMenuVo> list = new LinkedList<>();
        menuVosTree.forEach(m -> {
            NavMenuVo menuVo = new NavMenuVo();
            menuVo.setName(m.getName());
            // 一级目录需要加斜杠，不然会报警告
            menuVo.setPath(Objects.isNull(m.getPid()) ? "/" + m.getPath() : m.getPath());
            MenuMetaVo menuMetaVo = new MenuMetaVo();
            menuMetaVo.setHidden(m.getHidden());
            menuMetaVo.setTitle(m.getTitle());
            menuMetaVo.setIcon(m.getIcon());
            menuMetaVo.setNoCache(m.getCache());
            menuMetaVo.setRequiresAuth(m.getRequiresAuth());
            menuMetaVo.setAlwaysShow(true);
            menuVo.setMeta(menuMetaVo);
            // 外部链接
            if (Boolean.TRUE.equals(m.getFrame())) {
                menuVo.setComponent(StringUtils.isEmpty(m.getComponent()) ? "Link" : m.getComponent());
            } else {
                if (Objects.isNull(m.getPid()) && Objects.equals(m.getType(), 0)) {  // 菜单布局
                    menuVo.setComponent(StringUtils.isEmpty(m.getComponent()) ? "Layout" : m.getComponent());
                } else if (Objects.equals(m.getType(), 0)) {   //菜单打开新页面
                    menuVo.setComponent(StringUtils.isEmpty(m.getComponent()) ? "ParentView" : m.getComponent());
                } else if (StringUtils.isNoneEmpty(m.getComponent())) {  // 路由或按钮
                    menuVo.setComponent(m.getComponent());
                }
            }
            List<SysMenuVo> childList = m.getChildren();

            // 存在下级菜单
            if (CollUtil.isNotEmpty(childList)) {
                menuVo.setRedirect("noRedirect");
                menuVo.setChildren(buildMenus(childList));
            } else if (Objects.isNull(m.getPid())) {
                NavMenuVo navMenuVo = new NavMenuVo();
                navMenuVo.setMeta(menuVo.getMeta());
                if (Boolean.FALSE.equals(m.getFrame())) {
                    navMenuVo.setPath("index");
                    navMenuVo.setName(menuVo.getName());
                    navMenuVo.setComponent(menuVo.getComponent());
                }
                menuVo.setName(null);
                menuVo.setMeta(null);
                menuVo.setChildren(Collections.singletonList(navMenuVo));
            }
            list.add(menuVo);

        });
        return list;
    }

    @Override
    public List<SysMenu> findListByRoleId(Long roleId) {
        return baseMapper.findListByRoleId(roleId);
    }

    @Override
    public List<SysMenuVo> findTree() {
        QueryWrapper<SysMenu> wrapper = new QueryWrapper<>();
        wrapper.orderByAsc("menu_sort");
        List<SysMenu> sysMenus = baseMapper.selectList(wrapper);
        List<SysMenuVo> sysMenuVos = CollectionBeanUtils.copyListProperties(sysMenus, SysMenuVo::new);
        return buildTree(sysMenuVos);
    }

    @Override
    public List<SysMenuVo> findListByPid(Long pid) {
        QueryWrapper<SysMenu> wrapper = new QueryWrapper<>();
        wrapper.eq("pid", pid);
        List<SysMenu> menus = baseMapper.selectList(wrapper);
        return CollectionBeanUtils.copyListProperties(menus, SysMenuVo::new);
    }

    //    @Override
//    public List<SysMenuVo> queryMenu() {
//        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
//
//        List<SysMenu> sysMenus = sysMenuMapper.selectList(queryWrapper).stream().filter((sysMenu -> sysMenu.getType()!=2)).collect(Collectors.toList());
//        List<MenuDto> menuDtoList = sysMenus.stream().map(MenuDto::buildMenuDto).collect(Collectors.toList());
//
//        //构建菜单树
//        LinkedList<MenuDto> menuDtoLinkedList = new LinkedList<>(buildTree(menuDtoList));
//
//        LogUtil.debug("构建菜单");
//        LogUtil.debug(JsonUtil.toJsonStr(menuDtoLinkedList));
//
//        SysMenuVo sysMenuVo = new SysMenuVo();
//        List<SysMenuVo> sysMenuVoList = menuDtoLinkedList.stream().map(sysMenuVo::buildMenu).collect(Collectors.toList());
//
//        //返回数据封装
//        LogUtil.debug("构建菜单最终结果");
//        LogUtil.debug(JsonUtil.toJsonStr(sysMenuVoList));
//        return sysMenuVoList;
//    }
//
//    @Override
//    public List<SysMenuVo> querySupMenu(Long pid) {
//        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
//        if (Objects.nonNull(pid)) {
//            queryWrapper.eq("pid", pid);
//        } else {
//            queryWrapper.isNull("pid");
//        }
//        List<SysMenu> sysMenus = sysMenuMapper.selectList(queryWrapper);
//        List<MenuDto> menuDtoList = sysMenus.stream().map(MenuDto::buildMenuDto).collect(Collectors.toList());
//
//        SysMenuVo sysMenuVo = new SysMenuVo();
//        List<SysMenuVo> sysMenuVos = menuDtoList.stream().map(sysMenuVo::buildMenu).collect(Collectors.toList());
//
//        LogUtil.debug("懒加载菜单最终结果");
//        LogUtil.debug(JsonUtil.toJsonStr(sysMenuVos));
//
//        return sysMenuVos;
//    }
//
//    @Override
//    public Long queryMenuSort(String sort) {
//        QueryWrapper<SysMenu> queryWrapper = new QueryWrapper<>();
//        queryWrapper.orderByDesc("menu_sort");
//        queryWrapper.last("limit 1");
//
//        Long menuSort = sysMenuMapper.selectOne(queryWrapper).getMenuSort();
//
//        return menuSort;
//    }
//
//    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
//    @Override
//    public boolean removeByIds(Collection<? extends Serializable> idList) {
//        List<SysMenu> sysMenus = sysMenuMapper.selectBatchIds(idList);
//        sysMenuMapper.deleteBatchIds(idList);
//
//        for (SysMenu menu : sysMenus
//        ) {
//            if (Objects.nonNull(menu.getPid())){
//                QueryWrapper<SysMenu> sysMenuQueryWrapper=new QueryWrapper<>();
//                sysMenuQueryWrapper.eq("menu_id",menu.getPid());
//                SysMenu sysMenu=sysMenuMapper.selectById(menu.getPid());
//                sysMenu.setSubCount(sysMenu.getSubCount()-1);
//                sysMenuMapper.update(sysMenu,sysMenuQueryWrapper);
//            }
//        }
//
//        // 还要删除相关联角色表
//        sysMenuMapper.deleteConnectedRoles(idList);
//        return true;
//    }
//
//    @Override
//    public void download(HttpServletResponse response, List<Long> ids) throws IOException {
//        List<SysMenu> menus = sysMenuMapper.selectBatchIds(ids);
//
//
//        List<Map<String, Object>> mapList = new ArrayList<>();
//        for (SysMenu menu : menus) {
//            Map<String, Object> map = new HashMap<>();
//            map.put("id", menu.getId());
//            map.put("父级菜单pid", menu.getPid());
//            map.put("子菜单总数", menu.getSubCount());
//            map.put("类型", menu.getType());
//            map.put("标题", menu.getTitle());
//            map.put("姓名", menu.getName());
//            map.put("组件", menu.getComponent());
//            map.put("排序", menu.getMenuSort());
//            map.put("图标名称", menu.getIcon());
//            map.put("图标地址", menu.getPath());
//            map.put("外链", menu.getiFrame());
//            map.put("缓存", menu.getCache());
//            map.put("隐藏", menu.getHidden());
//            map.put("权限标识", menu.getComponent());
//            map.put("创建于", menu.getCreateBy());
//            map.put("创建时间", menu.getCreateTime());
//            map.put("更新于", menu.getUpdateBy());
//            map.put("更新时间", menu.getUpdateTime());
//            mapList.add(map);
//        }
//
//
//        FileUtil.downloadExcel(mapList, response);
//    }
//
//    @Override
//    public void addMenu(SysMenu sysMenu) {
//        sysMenuMapper.insert(sysMenu);
//        if (Objects.nonNull(sysMenu.getPid())) {
//            QueryWrapper<SysMenu> queryWrapper=new QueryWrapper<>();
//            queryWrapper.eq("menu_id",sysMenu.getPid());
//            SysMenu s = sysMenuMapper.selectById(sysMenu.getPid());
//            s.setSubCount(s.getSubCount() + 1);
//            sysMenuMapper.update(s, queryWrapper);
//        }
//    }
}
